<?php

    class TemplateEngine
    {
        private $filelist   = array();
        public $vars       = array();
        private $templates  = array();
        private $root       = "";
        private $last       = "";
        private $strict     = false;

        public function __construct( $pathToTemplates = "" )
        {
            if ( !empty($pathToTemplates) )
            {
                $this->setRoot($pathToTemplates);
            }
        }

        public function setRoot( $root )
        {
            $root = str_replace('\\', '/', "$root");
            $root = rtrim($root, '/').'/';
            if ( DIRECTORY_SEPARATOR != '/' )
            {
                $root = str_replace('/', DIRECTORY_SEPARATOR, $root);
            }

            if( is_dir($root) )
            {
                $this->root = $root;
            }
            else
            {
                $this->root = "";
                $this->warning("Specified root dir [$root] is not a directory");
            }
        }

        public function strict( $strict )
        {
            $this->strict = (bool) $strict;
        }

        public function parse( $varName, $fileTags )
        {
            $this->last = $varName;
            if ( is_array($fileTags) )
            {
                foreach ( $fileTags as $tag )
                {
                    $this->parse( $varName, (string) $tag );
                }
            }
            else
            {
                $tag = (string) $fileTags;

                $append = false;
                if( $tag[0] == '.' )
                {
                    $append = true;
                    $tag = substr($tag, 1);
                }

                if ( !isset($this->templates[$tag]) )
                {
                    $filename = $this->filelist[$tag];
                    $this->templates[$tag] = $this->getTemplate($filename);
                }

                $value = $append ? $this->get($varName) : '';
                $template = $this->templates[$tag];
                $value .= $this->parseTemplate( $template );

                $this->set( $varName, $value );
            }
        }

        public function generate( $varName = null )
        {
            if ( empty($varName) )
            {
                $varName = $this->last;
            }

            if ( !isset($this->vars[$varName]) )
            {
                $this->warning("Nothing parsed, nothing printed");
            }
            else
            {
                echo $this->vars[$varName];
            }
        }

        public function getGenerated( $varName = null )
        {
            if ( empty($varName) )
            {
                $varName = $this->last;
            }
            return isset($this->vars[$varName]) ? $this->vars[$varName] : '';
        }

        public function define( $tag, $filename = '' )
        {
            if ( is_array($tag) )
            {
                $fileList = $tag;
                if ( !empty($fileList) )
                {
                    $this->filelist = array_merge( $this->filelist, $fileList );
                }
            }
            else
            {
                $this->filelist["$tag"] = $filename;
            }
        }

        public function clearAll()
        {
            $this->clearVars();
            $this->filelist = array();
            $this->templates = array();
        }

        public function clearVars()
        {
            $this->last = '';
            $this->vars = array();
        }

        public function set( $name, $value = '', $htmlEncode = false )
        {
            if ( is_array($name) )
            {
                $values = $name;
                foreach ( $values as $name => $value )
                {
                    if ( !empty($name) )
                    {
                        $this->vars["$name"] = $htmlEncode ? $this->htmlEncode($value) : "$value";
                    }
                }
            }
            else if ( !empty($name) )
            {
                $this->vars["$name"] = $htmlEncode ? $this->htmlEncode($value) : "$value";
            }
        }

        public function setArr( $name, $value )
        {
            $this->vars["$name"] = $value;
        }

        public function get( $name )
        {
            if ( !empty($name) && isset($this->vars["$name"]) )
            {
                return $this->vars["$name"];
            }
            return '';
        }

        public function getTemplate( $template, $vars = null )
        {
            if ( empty($this->root) )
            {
                $this->error("Cannot open template. Root not valid.");
                return false;
            }

            $filename = "";
            $language = Core::GetLanguage();
            if ( $language != SiteLanguage::EN )
            {
                $filename = $this->root . "lng/{$language}/{$template}";
            }

            if ( empty( $filename ) || !file_exists( $filename ) )
            {
                $filename = $this->root . "$template";
            }
            $relativeDir = str_replace( PATH_TEMPLATES, "", str_replace( "\\", "/", $this->root ) );
            $relativeTemplatePath = $relativeDir . "/" . $template;

            if (is_array($vars))
            {
                $this->vars = $vars;
            }

            $this->vars['LNG'] = TemplateLanguage::GetTemplateLngVars( $relativeTemplatePath, $language, $this );
            $this->vars['THIS_LNG'] = Core::GetLanguage();
            $this->vars['CONTENT_SERVER_URL'] = Core::GetContentServerUrl();
            $this->vars['SITE_ID'] = Core::Config()->site_id;

            $contents = self::getView( $filename, $this->vars );

            return $contents;
        }

        private function parseTemplate( $template )
        {
            if ( !$this->strict )
            {
                // Silently remove anything not already found
                $template = preg_replace("/\{\w+\}/", "", $template );
            }
            else
            {
                if ( preg_match_all( "/\{(\w+)\}/", $template, $matches, PREG_SET_ORDER ) )
                {
                    foreach ($matches as $match)
                    {
                        $this->warning("[TemplateEngine]: no value found for variable: ". $match[1]);
                    }
                }
            }

            return $template;
        }

        private function warning( $message )
        {
            trigger_error( $message, E_USER_WARNING );
        }

        private function error( $message )
        {
            ob_start();
            debug_print_backtrace();
            $trace = ob_get_clean();
            trigger_error( "$message\n" . $trace, E_USER_WARNING /* E_USER_ERROR */ );
        }

        private function htmlEncode( $value )
        {
            return htmlentities( iconv( 'UTF-8', 'UTF-8//IGNORE', $value), ENT_QUOTES, 'UTF-8');
        }

        /**
         * Returns completely parsed template
         *
         * @param string $templateFile is a absolute physical path to the template
         * @param array $markers
         * @return string
         */
        public static function getView( $templateFile, $markers = array() )
        {
            $smarty = new Smarty();
            $smarty->template_dir  = SmartyConfig::SMARTY_TEMPLATES;
            $smarty->compile_dir   = SmartyConfig::SMARTY_COMPILE_DIR;
            $smarty->compile_check = true;
            $smarty->debugging = true;

            $markers['CONTENT_SERVER_URL'] = Core::GetContentServerUrl();
            $markers['SUPPORT_EMAIL']      = SUPPORT_FS_COM_BOX;
            $markers['SALES_EMAIL']        = SALES_IS_COM_BOX;
            $markers['CURRENT_SCHEMA']     = Request::IsSecure() ? "https" : "http";

            $cacheBusterEnabled = defined('CACHE_BUSTER_ENABLE') ? CACHE_BUSTER_ENABLE : false;
            if ( $cacheBusterEnabled )
            {
                $cacheBuster = new CacheBuster(CacheBuster::SMARTY_TEMPLATE_TYPE);
                $smarty->registerFilter('post', array($cacheBuster, 'ModifyContent'));
                $markers = $cacheBuster->PrepareTemplateVars($markers);
            }

            if ( isset ( $markers ) && count( $markers ) > 0 )
            {
                foreach ($markers as $key => $value)
                {
                    $smarty->assign( $key , $value );
                }
            }
            return $smarty->fetch( $templateFile );
        }

        /**
         * Shows template.
         *
         * @param string $templateFile
         * @param array $markers
         */
        public static function showTemplate( $templateFile, $markers = array() )
        {
            echo self::getView( $templateFile, $markers );
        }
    }

?>